/**
 * Notes: 设备状态监控服务 - 基于现有device_service.js的MQTT实现
 * Date: 2025-01-27
 */

const BaseService = require('./base_service.js');
const DeviceModel = require('../model/device_model.js');
const timeUtil = require('../../framework/utils/time_util.js');
const util = require('../../framework/utils/util.js');
const AppError = require('../../framework/core/app_error.js');
const appCode = require('../../framework/core/app_code.js');
const mqtt = require('mqtt');
const config = require('../../config/config.js');

class DeviceStatusMonitor extends BaseService {

    constructor() {
        super();
        // 复用DeviceService的MQTT静态配置
        this.mqttConfig = {
            protocol: 'mqtt',
            host: 'mqtt.geek-smart.cn',
            port: 1883,
            username: 'DZcZhkJkcRQz',
            password: 'hYvkOOCvRuChYUYHKZ',
            clientId: 'vIGuEvWZmWFk_monitor' // 使用不同的clientId避免冲突
        };
        this.mqttClient = null;
        this.isMonitoring = false;
        this.deviceStatusCache = new Map(); // 设备状态缓存
        this.lastStatusCheck = new Map(); // 上次状态检查时间
        this.statusCheckInterval = 30000; // 30秒检查一次
        this.offlineThreshold = 60000; // 60秒无响应视为离线
    }

    /**
     * 启动设备状态监控
     */
    async startMonitoring() {
        if (this.isMonitoring) {
            console.log('设备状态监控已在运行中');
            return;
        }

        try {
            console.log('启动设备状态监控服务...');
            await this.initMqttConnection();
            await this.subscribeToDeviceTopics();
            this.startStatusCheckTimer();
            this.isMonitoring = true;
            console.log('设备状态监控服务启动成功');
        } catch (error) {
            console.error('启动设备状态监控失败:', error);
            throw error;
        }
    }

    /**
     * 停止设备状态监控
     */
    async stopMonitoring() {
        console.log('停止设备状态监控服务...');
        this.isMonitoring = false;
        
        if (this.statusCheckTimer) {
            clearInterval(this.statusCheckTimer);
            this.statusCheckTimer = null;
        }

        if (this.mqttClient) {
            try {
                this.mqttClient.end(true);
            } catch (error) {
                console.warn('关闭MQTT连接时发生错误:', error);
            }
            this.mqttClient = null;
        }

        console.log('设备状态监控服务已停止');
    }

    /**
     * 初始化MQTT连接 - 参照device_service.js实现
     */
    async initMqttConnection() {
        if (this.mqttClient && this.mqttClient.connected) {
            console.log('MQTT监控连接已存在');
            return;
        }

        try {
            console.log('建立MQTT监控连接...');
            const options = {
                host: this.mqttConfig.host,
                port: this.mqttConfig.port,
                username: this.mqttConfig.username,
                password: this.mqttConfig.password,
                clientId: this.mqttConfig.clientId,
                reconnectPeriod: 5000, // 监控服务需要自动重连
                connectTimeout: 10000,
                clean: true,
                keepalive: 60,
                protocolVersion: 4
            };

            this.mqttClient = mqtt.connect(options);

            return new Promise((resolve, reject) => {
                const timeout = setTimeout(() => {
                    reject(new Error('MQTT连接超时'));
                }, 15000);

                this.mqttClient.on('connect', () => {
                    clearTimeout(timeout);
                    console.log('MQTT监控连接成功');
                    resolve();
                });

                this.mqttClient.on('error', (error) => {
                    clearTimeout(timeout);
                    console.error('MQTT监控连接错误:', error);
                    reject(error);
                });

                this.mqttClient.on('message', (topic, message) => {
                    this.handleDeviceStatusMessage(topic, message);
                });

                this.mqttClient.on('close', () => {
                    console.warn('MQTT监控连接已关闭');
                });

                this.mqttClient.on('disconnect', () => {
                    console.warn('MQTT监控连接已断开');
                });
            });
        } catch (error) {
            console.error('MQTT监控连接初始化失败:', error);
            throw error;
        }
    }

    /**
     * 订阅所有设备的状态主题
     */
    async subscribeToDeviceTopics() {
        try {
            // 获取所有设备列表
            const devices = await DeviceModel.getAll({
                type: { $ne: 'access_control' } // 排除门禁设备
            }, 'subscribeTopics,publishTopic,_id,name');

            console.log(`找到 ${devices.length} 个设备，开始订阅状态主题`);

            for (const device of devices) {
                await this.subscribeDeviceStatusTopic(device);
            }

            console.log('设备状态主题订阅完成');
        } catch (error) {
            console.error('订阅设备状态主题失败:', error);
            throw error;
        }
    }

    /**
     * 订阅单个设备的状态主题
     */
    async subscribeDeviceStatusTopic(device) {
        if (!this.mqttClient || !this.mqttClient.connected) {
            console.warn('MQTT客户端未连接，跳过订阅');
            return;
        }

        try {
            // 解析设备的状态主题 - 参照device_service.js的主题解析逻辑
            let statusTopic = null;
            
            if (Array.isArray(device.subscribeTopics) && device.subscribeTopics.length > 0) {
                statusTopic = device.subscribeTopics[0];
            } else if (typeof device.subscribeTopics === 'string' && device.subscribeTopics) {
                statusTopic = device.subscribeTopics;
            } else if (device.publishTopic) {
                // 如果没有订阅主题，使用发布主题作为状态主题
                statusTopic = device.publishTopic.replace('/control', '/status');
            }

            if (statusTopic) {
                if (!statusTopic.startsWith('/')) {
                    statusTopic = '/' + statusTopic;
                }
                
                this.mqttClient.subscribe(statusTopic, (error) => {
                    if (error) {
                        console.error(`订阅设备 ${device._id} 状态主题失败:`, error);
                    } else {
                        console.log(`已订阅设备 ${device._id} 状态主题: ${statusTopic}`);
                    }
                });
            } else {
                console.warn(`设备 ${device._id} 缺少状态主题配置`);
            }
        } catch (error) {
            console.error(`订阅设备 ${device._id} 状态主题时发生错误:`, error);
        }
    }

    /**
     * 处理设备状态消息
     */
    handleDeviceStatusMessage(topic, message) {
        try {
            const messageStr = message.toString();
            let statusData;
            
            try {
                statusData = JSON.parse(messageStr);
            } catch (parseError) {
                console.warn(`解析设备状态消息失败: ${messageStr}`);
                return;
            }

            // 从主题中提取设备标识
            const deviceId = this.extractDeviceIdFromTopic(topic);
            if (!deviceId) {
                console.warn(`无法从主题 ${topic} 中提取设备ID`);
                return;
            }

            // 更新设备状态缓存
            const currentTime = Date.now();
            const deviceStatus = {
                deviceId: deviceId,
                topic: topic,
                switchStatus: this.parseSwitchStatus(statusData),
                isOnline: true,
                lastUpdateTime: currentTime,
                rawData: statusData
            };

            this.deviceStatusCache.set(deviceId, deviceStatus);
            this.lastStatusCheck.set(deviceId, currentTime);

            console.log(`设备 ${deviceId} 状态更新:`, {
                switchStatus: deviceStatus.switchStatus,
                topic: topic,
                timestamp: new Date(currentTime).toISOString()
            });

            // 触发状态变化事件处理
            this.onDeviceStatusChange(deviceStatus);

        } catch (error) {
            console.error('处理设备状态消息时发生错误:', error);
        }
    }

    /**
     * 从MQTT主题中提取设备ID
     */
    extractDeviceIdFromTopic(topic) {
        // 尝试多种主题格式解析设备ID
        // 格式1: /device/{deviceId}/status
        // 格式2: /{storeId}/device/{deviceId}/status
        // 格式3: /mock/device/{deviceId}/status
        
        const patterns = [
            /\/device\/([^\/]+)\/status/,
            /\/[^\/]+\/device\/([^\/]+)\/status/,
            /\/mock\/device\/([^\/]+)\/status/,
            /\/([^\/]+)\/status/ // 简单格式
        ];

        for (const pattern of patterns) {
            const match = topic.match(pattern);
            if (match && match[1]) {
                return match[1];
            }
        }

        return null;
    }

    /**
     * 解析开关状态 - 参照device_service.js的消息格式
     */
    parseSwitchStatus(statusData) {
        // 根据device_service.js中的消息格式: { type: 'event', key: 1/0 }
        if (statusData && typeof statusData.key === 'number') {
            return statusData.key === 1 ? 'on' : 'off';
        }
        
        // 兼容其他可能的状态格式
        if (statusData && typeof statusData.status === 'string') {
            return statusData.status.toLowerCase();
        }
        
        if (statusData && typeof statusData.switch === 'boolean') {
            return statusData.switch ? 'on' : 'off';
        }

        return 'unknown';
    }

    /**
     * 设备状态变化事件处理
     */
    onDeviceStatusChange(deviceStatus) {
        // 这里可以添加状态变化的业务逻辑
        // 例如：异常检测、告警触发等
        
        // 检查设备是否异常
        if (this.isDeviceAbnormal(deviceStatus)) {
            this.handleDeviceAbnormal(deviceStatus);
        }
    }

    /**
     * 检查设备是否异常
     */
    isDeviceAbnormal(deviceStatus) {
        // 简单的异常检测逻辑
        // 可以根据实际需求扩展
        
        // 检查开关状态是否异常
        if (deviceStatus.switchStatus === 'unknown') {
            return true;
        }

        return false;
    }

    /**
     * 处理设备异常
     */
    handleDeviceAbnormal(deviceStatus) {
        console.warn(`检测到设备异常:`, {
            deviceId: deviceStatus.deviceId,
            switchStatus: deviceStatus.switchStatus,
            lastUpdateTime: new Date(deviceStatus.lastUpdateTime).toISOString()
        });

        // 这里可以添加异常处理逻辑
        // 例如：发送告警、记录日志、尝试恢复等
    }

    /**
     * 启动状态检查定时器
     */
    startStatusCheckTimer() {
        if (this.statusCheckTimer) {
            clearInterval(this.statusCheckTimer);
        }

        this.statusCheckTimer = setInterval(() => {
            this.checkDevicesOnlineStatus();
        }, this.statusCheckInterval);

        console.log(`状态检查定时器已启动，检查间隔: ${this.statusCheckInterval}ms`);
    }

    /**
     * 检查设备在线状态
     */
    checkDevicesOnlineStatus() {
        const currentTime = Date.now();
        
        for (const [deviceId, lastCheckTime] of this.lastStatusCheck.entries()) {
            const timeSinceLastCheck = currentTime - lastCheckTime;
            
            if (timeSinceLastCheck > this.offlineThreshold) {
                // 设备可能离线
                const deviceStatus = this.deviceStatusCache.get(deviceId);
                if (deviceStatus && deviceStatus.isOnline) {
                    console.warn(`设备 ${deviceId} 可能已离线，上次更新时间: ${new Date(lastCheckTime).toISOString()}`);
                    
                    // 更新设备状态为离线
                    deviceStatus.isOnline = false;
                    this.deviceStatusCache.set(deviceId, deviceStatus);
                    
                    // 触发离线事件处理
                    this.onDeviceOffline(deviceStatus);
                }
            }
        }
    }

    /**
     * 设备离线事件处理
     */
    onDeviceOffline(deviceStatus) {
        console.warn(`设备离线:`, {
            deviceId: deviceStatus.deviceId,
            lastUpdateTime: new Date(deviceStatus.lastUpdateTime).toISOString()
        });

        // 这里可以添加离线处理逻辑
        // 例如：发送离线告警、更新数据库状态等
    }

    /**
     * 获取设备当前状态
     */
    getDeviceStatus(deviceId) {
        return this.deviceStatusCache.get(deviceId) || null;
    }

    /**
     * 获取所有设备状态
     */
    getAllDevicesStatus() {
        const statusList = [];
        for (const [deviceId, status] of this.deviceStatusCache.entries()) {
            statusList.push(status);
        }
        return statusList;
    }

    /**
     * 获取在线设备数量
     */
    getOnlineDevicesCount() {
        let count = 0;
        for (const status of this.deviceStatusCache.values()) {
            if (status.isOnline) {
                count++;
            }
        }
        return count;
    }

    /**
     * 获取离线设备数量
     */
    getOfflineDevicesCount() {
        let count = 0;
        for (const status of this.deviceStatusCache.values()) {
            if (!status.isOnline) {
                count++;
            }
        }
        return count;
    }

    /**
     * 手动检查单个设备状态
     */
    async checkDeviceStatus(deviceId) {
        try {
            // 这里可以主动发送状态查询指令
            // 暂时返回缓存中的状态
            const cachedStatus = this.getDeviceStatus(deviceId);
            if (cachedStatus) {
                return {
                    success: true,
                    data: cachedStatus
                };
            } else {
                return {
                    success: false,
                    message: '设备状态未找到'
                };
            }
        } catch (error) {
            console.error(`检查设备 ${deviceId} 状态失败:`, error);
            return {
                success: false,
                message: error.message
            };
        }
    }
}

module.exports = DeviceStatusMonitor;